/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package cl.darksigns.webstat.client;

import cl.darksigns.webstat.back.vo.DataVO;
import cl.darksigns.webstat.back.vo.HeaderVO;
import cl.darksigns.webstat.back.vo.RequestVO;
import cl.darksigns.webstat.back.vo.SessionVO;
import cl.darksigns.webstat.back.vo.WebStatVO;
import cl.darksigns.webstat.back.exception.WebStatException;
import cl.darksigns.webstat.back.vo.WebStatSpecificVO;
import cl.darksigns.webstat.client.connection.Connection;
import cl.darksigns.webstat.client.connection.HTTPConnection;
import cl.darksigns.webstat.client.connection.RMIConnection;
import com.thoughtworks.xstream.XStream;
import java.util.ArrayList;
import java.util.Enumeration;
import java.util.ResourceBundle;
import javax.servlet.http.HttpServletRequest;
import org.apache.log4j.Logger;

/**
 * Client for WebStat, this will be distributed between all applications
 * that uses WebStat information.
 * @author Vìctor Yañez
 */
public class WebStatClient {

    private static WebStatClient _instance = null;
    private static Logger logger = null;
    private Connection connType = null;

    /**
     *
     * @return
     * @throws WebStatException
     */
    public static WebStatClient getInstance() throws WebStatException {
        if (_instance == null) {
           
            _instance = new WebStatClient();
             logger.info("New instance of WebStatClient");
        }
        return _instance;
    }

    private WebStatClient() throws WebStatException {
        logger = Logger.getLogger("wst_log4j.properties");

        ResourceBundle resource = ResourceBundle.getBundle("wst_client");
        String communicationType = resource.getString("COMMUNICATION");
        logger.debug("communicationType: " + communicationType);
        if ("RMI".equalsIgnoreCase(communicationType)) {
            logger.debug("implementing RMI Communication");
            connType = new RMIConnection();
        } else if ("HTTP".equalsIgnoreCase(communicationType)) {
            logger.debug("Implementing HTTP Communication");
            connType = new HTTPConnection();
        } else {
            throw new WebStatException("Misconfiguration in communication type - value: " + communicationType);
        }
    }


    /**
     * 
     * @param request
     * @param userId
     * @param eventId
     * @param methodType
     * @return
     * @throws WebStatException
     */
    public String saveStat(HttpServletRequest request,String userId,
		String eventId,
		String methodType) throws WebStatException {


        WebStatVO webStat = new WebStatVO();
        RequestVO requestVO = new RequestVO();

        /**
         * Llenando Valores para Request
         */
        //requestVO.setReqAppId(Integer.parseInt("1"));
        requestVO.setReqEventId(eventId);
        requestVO.setReqSessionId(request.getSession().getId().trim());
        requestVO.setReqSourceUri(request.getRequestURI());
        requestVO.setReqTargetUri(request.getContextPath());
        requestVO.setReqType(methodType);
        requestVO.setReqUserId(userId);
        webStat.setRequestValues(requestVO);

        /**
         * Header section
         */
        ArrayList<HeaderVO> headerData = new ArrayList<HeaderVO>();

        int cnt = 1;
        for (Enumeration headers = request.getHeaderNames();headers.hasMoreElements();) {
            HeaderVO head = new HeaderVO();
            String name = (String) headers.nextElement();
            if (!("cookie").equalsIgnoreCase(name.trim())) {
                String value = request.getHeader(name);
                head.setReqHeadId(cnt);
                head.setReqHeadName(name);
                head.setReqHeadStringValue(value);
                headerData.add(head);
                cnt++;
            }
        }
        webStat.setHeaderValues(headerData);

        /**
         * Data section
         */
        cnt = 1;
        ArrayList<DataVO> dataData = new ArrayList<DataVO>();
        for (Enumeration params = request.getParameterNames();
                params.hasMoreElements();) {
            DataVO data = new DataVO();
            String name = (String) params.nextElement();
            String value = request.getParameter(name);
            data.setReqDataName(name);
            data.setReqDataStringValue(value);
            data.setReqDataId(cnt);
            dataData.add(data);
            cnt++;

        }
        webStat.setDataValues(dataData);

        /**
         * Data section
         */
        ArrayList<SessionVO> dataSession = new ArrayList<SessionVO>();
        cnt = 1;
        
        for (Enumeration params = request.getSession().getAttributeNames();
                params.hasMoreElements();) {

            SessionVO session = new SessionVO();
            String name = (String) params.nextElement();
            Object objeto = request.getSession().getAttribute(name);
            logger.info("name: " + name);
            if (objeto instanceof String) {
                session.setReqSessId(cnt);
                session.setReqSessName(name);
                session.setReqSessStringValue(objeto.toString());
                dataSession.add(session);
                cnt++;
            }
        }
        webStat.setSessionValues(dataSession);
        XStream xstream = new XStream();
        String xml = xstream.toXML(webStat);
        logger.info("xml : " + xml);
        connType.sendInformation(xml);
        return "ERC_00";
    }

    /**
     * 
     * @param product
     * @param description
     * @param transactionType
     * @return
     */
    public String saveStat(String product, String productDesc, String productCategory, String transactionType) {
        try {

            ClientResource props = ClientResource.getInstance();
            logger.info("Sending specific client information");
            WebStatSpecificVO wst = new WebStatSpecificVO();

            wst.setApplicationId(Integer.parseInt(props.getResource("APP_ID")));
            wst.setProduct(product);
            wst.setProductDesc(productDesc);
            wst.setProductCategory(productCategory);
            wst.setEventType(transactionType);
            XStream xstream = new XStream();
            String xml = xstream.toXML(wst);
            connType.sendSpecificInformation(xml);
        } catch (WebStatException ex) {
            ex.printStackTrace();
            logger.error("Error:  " +ex.getMessage());
            return "ERC_01";
        }catch(Exception ex){
            ex.printStackTrace();
            logger.error("Error:  " +ex.getMessage());
            return "ERC_01";
        }
        return "ERC_00";
    }
}
